package dyyx;

import java.io.InputStream;
import java.sql.Connection;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.jdbc.SqlRunner;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.session.SqlSessionManager;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;

import dyyx.data.UserDO;
import dyyx.data.UserDTO;
import dyyx.mapper.UserMapper;
import dyyx.util.CommUtil;

public class MybatisTest {
	
	

	public static void main(String[] args) throws Exception {
		System.out.println("hello,mybatis," + new Date());

		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		// 使用配置文件创建 SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		boolean autocommit = true;
		// 获取 SqlSession ， 封装了jdbc connection 
		SqlSession session = sqlSessionFactory.openSession(autocommit);
		
		System.out.println("session=" + session);
		System.out.println("autocommit=" + autocommit);
		System.out.println("session.conn.autoCommit=" + session.getConnection().getAutoCommit());
		
		SqlSessionManager sqlSessionManager = SqlSessionManager.newInstance(sqlSessionFactory);
		// SqlSessionManager 继承了 SqlSessionFactory 和 SqlSession
		// SqlSessionManager集成了 sqlSessionFactory和SqlSession 的功能


		
		// init 创建表 insert 初始数据
		String sqlstr = CommUtil.readFromResource("db/data.sql", null);
		System.out.println(sqlstr);
		String[]sqls = StringUtils.split(sqlstr, ";");
		for(String sql:sqls){
			if(StringUtils.isBlank(sql)){
				continue;
			}
			// 获取 jdbc 连接 执行 初始化语句
			session.getConnection().createStatement().executeUpdate(sql);
		}
		
		System.out.println("\n\n\n\n\n\n");

        // 1  java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
		// 参数类型为Long parameterType="Long" ， 传入整数 报类型转换异常
		// statement = namespace.id
		UserDO user = session.selectOne("dyyx.mapper.UserMapper.getById", 1L);
		// UserDO user = (UserDO)session.selectOne("user.getById", 1L);
		// 不需要 类型强转
		System.out.println("user=" + user+"\n\n");
		
		
		UserDTO userDTO = session.selectOne("dyyx.mapper.UserMapper.getById2", 1L);
		System.out.println("userDTO=" + userDTO+"\n\n");
		
		// 字段大小写测试
		// 小写
		userDTO = session.selectOne("dyyx.mapper.UserMapper.getById3", 1L);
		System.out.println("userDTO=" + userDTO+"\n\n");

		// 大写
	    userDTO = session.selectOne("dyyx.mapper.UserMapper.getById4", 1L);
		System.out.println("userDTO=" + userDTO+"\n\n");

		System.out.println("\n\n\n\n\n\n");

		
		user = sqlSessionManager.selectOne("dyyx.mapper.UserMapper.getById", 1L);
		
		
	    UserMapper userMapper = session.getMapper(UserMapper.class);
	    user = userMapper.getById(1L);
		System.out.println("user.userMapper.getById=" + user);

		
		
		UserDO usernew = new UserDO();
		usernew.setId(1L);
		usernew.setHeight(8);
		usernew.setWeight(18.88);
		
		int updateResult = session.update("dyyx.mapper.UserMapper.update", usernew);
		System.out.println("updateResult=" + updateResult);

		user = session.selectOne("dyyx.mapper.UserMapper.getById", 1L);
		System.out.println("user.afterUpdate=" + user);
		
		updateResult = session.update("dyyx.mapper.UserMapper.update2", usernew);
		System.out.println("updateResult2=" + updateResult);

		updateResult = session.update("dyyx.mapper.UserMapper.update3", usernew);
		System.out.println("updateResult3=" + updateResult);

		
		List<UserDTO> userDTOList = session.selectList("dyyx.mapper.UserMapper.getAllUserDTOs", null); 
		
		for(UserDTO item:userDTOList){
			System.out.println(item.getClass()+","+item);

		}
		
		// 错误写法  Cannot cast from List<Object> to List<UserDTO>
		// List<UserDTO> userDTOList2 = (List<UserDTO>)session.selectList("user.getAllUserDTOs", null); 
		
		System.out.println(session.getConnection().isClosed());

		System.out.println("connection1="+System.identityHashCode(session.getConnection()));
		
		UserDO queryDO = new UserDO();
		
		List<UserDO> users = session.selectList("dyyx.mapper.UserMapper.query", queryDO); 

		queryDO.setWeight(5.0);
		users = session.selectList("dyyx.mapper.UserMapper.query", queryDO); 
		
		queryDO.setHeight(9);
		users = session.selectList("dyyx.mapper.UserMapper.query", queryDO); 
		
		
		
		
		session.close();
		// 关闭session ，归还 jdbc连接
		// Returned connection xxx to pool.
		
		// org.apache.ibatis.executor.ExecutorException: Executor was closed.
		// System.out.println(session.getConnection().isClosed());
		
		session = sqlSessionFactory.openSession(autocommit);
		System.out.println("connection2="+System.identityHashCode(session.getConnection()));
		session.close();
		
		
		// 代码创建 SqlSessionFactory
		System.out.println("\n\n buildSqlSessionFactory ");		
		sqlSessionFactory = buildSqlSessionFactory();
		session = sqlSessionFactory.openSession(autocommit);
		user = sqlSessionManager.selectOne("dyyx.mapper.UserMapper.getById", 1L);
		System.out.println("user=" + user);
		
		//
		
		sqlrun(session.getConnection());

		session.close();
		
		
		//
		
		
		
		
	}
	
	
	
	/*
	 * 代码创建 SqlSessionFactory
	 */
	private static SqlSessionFactory buildSqlSessionFactory() throws Exception {
		// 连接池
		PooledDataSource dataSource = new PooledDataSource();
		dataSource.setDriver("org.h2.Driver");
		dataSource.setUsername("sa");
		dataSource.setPassword("");
		dataSource.setUrl("jdbc:h2:mem:testdb");
		// dataSource.setDefeultAutoCommit(false);
		// MyBatis JDBC 事务
		TransactionFactory transactionFactory = new JdbcTransactionFactory();
		Environment environment = new Environment("dev", transactionFactory, dataSource);
		//
		Configuration configuration = new Configuration(environment);
		// MyBatis 类型别名
		// configuration.getTypeAliasRegistry().registerAlias("user",
		// UserDO.class);
		// configuration.addMapper(UserMapper.class);
		Set<String> mappers = new LinkedHashSet<>();
		mappers.add("mapper/UserMapper.xml");
		for (String resource : mappers) {
			InputStream inputStream = Resources.getResourceAsStream(resource);
			XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource,
					configuration.getSqlFragments());
			mapperParser.parse();
			inputStream.close();
		}

		SqlSessionFactory SqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
		return SqlSessionFactory;
	}
	
	
	private static void sqlrun(Connection cn)throws Exception{
		String sql = "select * from t_user";
		SqlRunner sqlRunner = new SqlRunner(cn);
		List<Map<String, Object>>  list = sqlRunner.selectAll(sql, new Object[]{});
		for(Map<String, Object> item:list){
			System.out.println(item);

		}
		Map<String, Object> row = list.get(0);
		Set<Map.Entry<String, Object>> kvs = row.entrySet();
		for(Map.Entry<String, Object> item:kvs){
			System.out.println(item.getValue().getClass());
		}

        // java.sql.Timestamp java.lang.Long java.lang.Integer java.lang.Double java.lang.String

		
	}
	
}
